<?php
/**
 * FastApp.
 * 10/23/24
 * @Author deepsea159
 * @Contact telegram:deepsea159
 */

namespace App\Fastapp\Api\Service\Account;

use App\Fastapp\Exception\TipException;
use App\Fastapp\FastappEmailService;
use App\Fastapp\FastappSmsService;
use App\Fastapp\Model\Account;
use App\Fastapp\Model\AccountLoginLog;
use App\Fastapp\Model\AccountSecurityKey;
use PragmaRX\Google2FA\Google2FA;

class SecurityCenterService
{
    public function getGoogle2FA(bool $reset = false, int $uid = 0): array
    {
        $uid = $uid ?: get_uid();
        $md = AccountSecurityKey::query()->firstOrCreate(['type' => 1, 'user_id' => $uid]);
        $google2fa = new Google2FA();
        if (!$md->status || $reset) {
            $md->key = $google2fa->generateSecretKey();
            if ($reset) $md->status = 0;
            $md->save();
        }
        $ac = Account::query()->where(['gene_id' => $uid])->first(['username', 'mobile', 'email', 'type']);
        $google2fa_name = array_column(api_cache()->getDictByKey('google2fa_name'), 'label', 'value');
        $company = $google2fa_name[$ac->type] . '(' . date('Y-m-d') . ')';
        $u = $ac->email ?: ($ac->mobile ?: $ac->username);
        $inlineUrl = $google2fa->getQRCodeUrl($company, $u, $md->key);
        return ['url' => $inlineUrl, 'key' => $md->key];
    }

    public function activeGoogle2FA(array $data): bool
    {
        $uid = get_uid();
        $md = AccountSecurityKey::query()->where(['type' => 1, 'user_id' => $uid])->first();
        $google2fa = new Google2FA();
        $valid = $google2fa->verifyKey($md->key, $data['facode'], 8);
        if ($valid) {
            $md->status = 1;
            return $md->save();
        }
        throw new TipException(fastapp_t('account.invalid_fail'));
    }

    public static function validateGoogle2FA(string|int $facode, int $uid = 0): bool
    {
        $uid = $uid ?: get_uid();
        $skey = AccountSecurityKey::query()->where(['type' => 1, 'user_id' => $uid])->value('key');
        if (!$skey) throw new TipException(fastapp_t('account.invalid_fail'));
        $google2fa = new Google2FA();
        if ($google2fa->verifyKey($skey, $facode, 8)) return true;
        throw new TipException(fastapp_t('account.invalid_verification_error'));
    }

    public function resetGoogle2FA(array $param): array
    {
        $uid = get_uid();
        if ($param['type'] == 2) {
            $email = Account::query()->where(['gene_id' => $uid])->value('email');
            FastappEmailService::validate($email, $param['vcode']);
        }
        if ($param['type'] == 3) {
            $ac = Account::query()->where(['gene_id' => $uid])->first(['mobile', 'code']);
            FastappSmsService::validate($ac->mobile, $param['vcode'], $ac->code);
        }
        return $this->getGoogle2FA(true, $uid);
    }

    public function loginLog(): array
    {
        $paginate = AccountLoginLog::query()
            ->select(['ip', 'region', 'agent', 'created_at'])
            ->where(['user_id' => get_uid()])
            ->orderByDesc('id')->simplePaginate();
        return ['list' => $paginate->items()];
    }
}